<?php
/************************************************************************
 Omnitrix - PHP Development Framework
 Copyright (C) 2012-2018 amonest(eastson@outlook.com)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
************************************************************************/

class omnitrix_html_table extends omnitrix_html_container
{
	protected $_id = null;
	protected $_title = null;
	protected $_class = null;
	protected $_head_rows = array();
	protected $_body_rows = array();
	protected $_foot_rows = array();
	protected $_form_rows = array();
	protected $_cell_count = 0;
	protected $_pager_info = array();
	protected $_link_pattern = null;
	protected $_bulk_actions = array();
	public $quick_search = null;

	public function __construct($title = null, $class = null, $pager_info = null, $link_pattern = null)
	{
		if (null !== $title) {
			$this->set_title($title);
		}

		if (null !== $class) {
			$this->set_class($class);
		}

		if (null !== $pager_info) {
			$this->set_list_pagination($pager_info, $link_pattern);
		}
	}

	public function set_id($id)
	{
		$this->_id = $id;
		return $this;
	}

	public function set_title($title)
	{
		$this->_title = $title;
		return $this;
	}

	public function set_class($class)
	{
		$this->_class = $class;
		return $this;
	}

	public function add_bulk_action($text, $url)
	{
		$this->_bulk_actions[] = array(
				'text' => $text,
				'url' => $url
		);
		return $this;
	}

	public function add_head_row($row_attribs = array())
	{
		$this->_head_rows[] = array(
				'cells' => array(),
				'attribs' => $row_attribs
		);
		return $this;
	}

	public function set_head_cell($cell_value, $cell_attribs = array())
	{
		if (count($this->_head_rows) == 0) {
			$this->add_head_row();
		}

		$row_index = count($this->_head_rows) - 1;
		$cell_index = count($this->_head_rows[$row_index]['cells']);
		$this->_head_rows[$row_index]['cells'][$cell_index] = array(
				'value' => $cell_value,
				'attribs' => $cell_attribs
		);

		if ($this->_cell_count <= $cell_index) {
			$this->_cell_count = $cell_index + 1;
		}

		return $this;
	}

	public function add_body_row($row_attribs = array())
	{
		$this->_body_rows[] = array(
				'cells' => array(),
				'attribs' => $row_attribs
		);
		return $this;
	}

	public function set_body_cell($cell_value, $cell_attribs = array())
	{
		if (count($this->_body_rows) == 0) {
			$this->add_body_row();
		}

		$row_index = count($this->_body_rows) - 1;
		$cell_index = count($this->_body_rows[$row_index]['cells']);
		$this->_body_rows[$row_index]['cells'][$cell_index] = array(
				'value' => $cell_value,
				'attribs' => $cell_attribs
		);

		if ($this->_cell_count <= $cell_index) {
			$this->_cell_count = $cell_index + 1;
		}

		return $this;
	}

	public function add_foot_row($row_attribs = array())
	{
		$this->_foot_rows[] = array(
				'cells' => array(),
				'attribs' => $row_attribs
		);
		return $this;
	}

	public function set_foot_cell($cell_value, $cell_attribs = array())
	{
		if (count($this->_foot_rows) == 0) {
			$this->add_foot_row();
		}

		$row_index = count($this->_foot_rows) - 1;
		$cell_index = count($this->_foot_rows[$row_index]['cells']);
		$this->_foot_rows[$row_index]['cells'][$cell_index] = array(
				'value' => $cell_value,
				'attribs' => $cell_attribs
		);

		if ($this->_cell_count <= $cell_index) {
			$this->_cell_count = $cell_index + 1;
		}

		return $this;
	}

	public function add_form_row($row_attribs = array())
	{
		$this->_form_rows[] = array(
				'form' => array(),
				'attribs' => $row_attribs
		);

		if ($this->_cell_count < 1) {
			$this->_cell_count = 1 ;
		}

		return $this;
	}

	public function add_form_input($label, $input, $required = false)
	{
		$this->add_form_row();

		$row_index = count($this->_form_rows) - 1;
		$this->_form_rows[$row_index]['form'] = array(
				'label' => $label,
				'input' => $input,
				'required' => $required
		);

		return $this;
	}

	public function add_form_entry($label, $input, $required = false)
	{
		return $this->add_form_input($label, $input, $required);
	}

	public function set_form_label($label)
	{
		if (count($this->_form_rows) == 0) {
			$this->add_form_row();
		}

		$row_index = count($this->_form_rows) - 1;
		$this->_form_rows[$row_index]['form']['label'] = $label;

		return $this;
	}

	public function set_form_input($input)
	{
		if (count($this->_form_rows) == 0) {
			$this->add_form_row();
		}

		$row_index = count($this->_form_rows) - 1;
		$this->_form_rows[$row_index]['form']['input'] = $input;

		return $this;
	}

	public function set_form_required($required)
	{
		if (count($this->_form_rows) == 0) {
			$this->add_form_row();
		}

		$row_index = count($this->_form_rows) - 1;
		$this->_form_rows[$row_index]['form']['required'] = $required;

		return $this;
	}

	public function set_list_pagination($pager_info, $link_pattern = null)
	{
		$this->_pager_info = $pager_info;
		$this->_link_pattern = $link_pattern;
		return $this;
	}

	public function render_html()
	{
		if (null === $this->_id) {
			$this->_id = otx_html_next_id('tablelist');
		}

		if ($this->_bulk_actions && null === $this->quick_search) {
			$this->quick_search = true;
		}

		$html = $this->_render_top_toolbox();
		$html .= otx_html_tag_start('div', array('class' => 'table-box', 'id' => $this->_id));

		if (!empty($this->_title)) {
			$html .= otx_html_tag_start('div', array('class' => 'title'))
					. $this->_title
					. otx_html_tag_end('div');
		}

		$table_attribs = array();

		if (!empty($this->_class)) {
			$table_attribs['class'] = $this->_class;
		}

		$html .= otx_html_tag_start('table', $table_attribs);

		if (count($this->_head_rows) > 0) {
			$html .= otx_html_tag_start('thead')
					. $this->_render_rows($this->_head_rows, 'th')
					. otx_html_tag_end('thead');
		}

		if (count($this->_body_rows) > 0) {
			$html .= otx_html_tag_start('tbody')
					. $this->_render_rows($this->_body_rows, 'td')
					. otx_html_tag_end('tbody');
		}

		if (count($this->_foot_rows) > 0) {
			$html .= otx_html_tag_start('tfoot')
					. $this->_render_rows($this->_foot_rows, 'td')
					. otx_html_tag_end('tfoot');
		}

		if (count($this->_form_rows) > 0) {
			$html .= otx_html_tag_start('tbody')
					. $this->_render_rows($this->_form_rows, 'td')
					. otx_html_tag_end('tbody');
		}

		$html .= otx_html_tag_end('table');
		$html .= otx_html_tag_end('div');
		$html .= $this->_render_pagination();

		return $html;
	}

	protected function _render_rows($rows, $tag_name = 'td')
	{
		$html = '';

		foreach ($rows as $row) {
			$html .= otx_html_tag_start('tr', $row['attribs']);

			if (isset($row['cells'])) {
				foreach ($row['cells'] as $cell) {
					$html .= otx_html_tag_start($tag_name, $cell['attribs'])
							. $cell['value']
							. otx_html_tag_end($tag_name);
				}
			} else {
				$form_label = isset($row['form']['label']) ? $row['form']['label'] : '';
				$form_input = isset($row['form']['input']) ? $row['form']['input'] : '';
				$form_required = isset($row['form']['required']) ? (bool) $row['form']['required'] : false;

				$html .= otx_html_tag_start($tag_name)
						. otx_html_tag_simple('label', $form_label)
						. otx_html_tag_start('div', array('class' => 'form-row'))
						. $form_input
						. ($form_required ? otx_html_tag_simple('em', '*') : '')
						. otx_html_tag_end('div')
						. otx_html_tag_end($tag_name);
			}


			$html .= otx_html_tag_end('tr');
		}

		return $html;
	}

	protected function _render_pagination()
	{
		if (empty($this->_pager_info) ||
			$this->_pager_info['record_count'] <= $this->_pager_info['page_size']) {
			return '';
		}

		$max_links = 5;

		$html = otx_html_tag_start('div', array('class' => 'pagination'))
				. otx_html_tag_simple('span', otx_language_parse('text_pages'), array('class' => 'pages'));

		if ($this->_pager_info['current_page'] > 1) {
			$previous_page = $this->_pager_info['current_page'] - 1;
			$previous_link = $this->_get_pager_link($previous_page);
			$html .= otx_html_tag_simple('a', otx_language_parse('text_go_previous'), array('class' => 'previous', 'href' => $previous_link));
		}

		$from_page = $this->_pager_info['current_page'] - floor($max_links / 2);
		$to_page = $this->_pager_info['current_page'] + floor($max_links / 2);

		if ($from_page <= 0) {
			$from_page = 1;
			$to_page = $from_page + $max_links - 1;
		}

		if ($to_page > $this->_pager_info['page_count']) {
			$to_page = $this->_pager_info['page_count'];
			$from_page = $this->_pager_info['page_count'] - $max_links + 1;
			if ($from_page <= 0) {
				$from_page = 1;
			}
		}

		if ($to_page == 0) {
			$to_page = $this->_pager_info['page_count'];
		}

		if ($from_page > 2) {
			$first_link = $this->_get_pager_link(1);
			$html .= otx_html_tag_simple('a', 1, array('class' => 'first', 'href' => $first_link))
					. otx_html_tag_simple('span', '...', array('class' => 'divider'));
		}

		for ($i = $from_page; $i <= $to_page; ++$i) {
			$page_link = $this->_get_pager_link($i);
			if ($this->_pager_info['current_page'] == $i) {
				$html .= otx_html_tag_simple('span', $i, array('class' => 'current'));
			} else {
				$html .= otx_html_tag_simple('a', $i, array('href' => $page_link));
			}
		}

		if ($to_page < $this->_pager_info['page_count']) {
			$last_link = $this->_get_pager_link($this->_pager_info['page_count']);
			$html .= otx_html_tag_simple('span', '...', array('class' => 'divider'))
					. otx_html_tag_simple('a', $this->_pager_info['page_count'], array('class' => 'last', 'href' => $last_link));
		}

		if ($this->_pager_info['current_page'] < $this->_pager_info['page_count']) {
			$next_page = $this->_pager_info['current_page'] + 1;
			$next_link = $this->_get_pager_link($next_page);
			$html .= otx_html_tag_simple('a', otx_language_parse('text_go_next'), array('class' => 'next', 'href' => $next_link));
		}

		$html .= otx_html_tag_end('div');
		return $html;
	}

	protected function _get_pager_link($page)
	{
		if (empty($this->_link_pattern)) {
			$this->_link_pattern = otx_request_append_query(otx_request_uri(),
					'current_page', 0);
		}

		return otx_request_append_query($this->_link_pattern, 'current_page', $page);
	}

	protected function _render_top_toolbox()
	{
		if (!$this->quick_search && empty($this->_bulk_actions)) {
			return '';
		}

		$html = otx_html_tag_start('div', array('class' => 'box'));

		if ($this->quick_search) {
			$html .= otx_html_tag_start('div', array('class' => 'quick-search', 'target-box' => '#' . $this->_id));
			$html .= otx_language_parse('text_quick_search');
			$html .= otx_html_form_text(null, otx_param_string('s'));
			$html .= otx_html_form_button(null, otx_language_parse('button_search'));
			$html .= otx_html_tag_end('div');
		}

		if ($this->_bulk_actions) {
			$html .= otx_html_tag_start('div', array('class' => 'bulk-actions', 'target-box' => '#' . $this->_id));
			$html .= otx_language_parse('text_bulk_actions');
			$html .= otx_html_tag_start('select');
			$html .= otx_html_tag_simple('option', otx_language_parse('text_select'), array('value' => ''));
			foreach ($this->_bulk_actions as $bulk_action) {
				$html .= otx_html_tag_simple('option', $bulk_action['text'], array('url' => $bulk_action['url']));
			}
			$html .= otx_html_tag_end('select');
			$html .= otx_html_form_button(null, otx_language_parse('button_bulk'));
			$html .= otx_html_tag_end('div');
		}

		$html .= otx_html_tag_end('div');
		return $html;
	}
}